package com.ibeeking.found.upms.b.rest.service.impl;

import com.ibeeking.found.upms.b.rest.service.ITenantAuthRoleService;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.upms.service.common.bo.TenantAuthRoleBO;
import com.ibeeking.found.upms.service.common.bo.TenantAuthRoleUserBO;
import com.ibeeking.found.upms.service.common.dos.ShopRoleTenantAuthRoleDO;
import com.ibeeking.found.upms.service.common.dos.TenantAuthRoleDO;
import com.ibeeking.found.upms.service.common.dos.TenantAuthRoleUserDO;
import com.ibeeking.found.upms.service.common.param.TenantAuthRoleParam;
import com.ibeeking.found.upms.service.common.query.TenantAuthRolePageQuery;
import com.ibeeking.found.upms.service.common.vo.TenantAuthRolePageVO;
import com.ibeeking.found.upms.service.common.vo.TenantAuthRoleVO;
import com.ibeeking.found.upms.service.mapper.ShopRoleTenantAuthRoleMapper;
import com.ibeeking.found.upms.service.mapper.TenantAuthRoleMapper;
import com.ibeeking.found.upms.service.mapper.TenantAuthRoleUserMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName TenantAuthRoleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-04-28 8:53
 **/
@Service
public class TenantAuthRoleServiceImpl implements ITenantAuthRoleService {

    @Resource
    private TenantAuthRoleMapper tenantAuthRoleMapper;
    @Resource
    private TenantAuthRoleUserMapper tenantAuthRoleUserMapper;
    @Resource
    private ShopRoleTenantAuthRoleMapper shopRoleTenantAuthRoleMapper;

    @Override
    public Page<TenantAuthRolePageVO> pageList(TenantAuthRolePageQuery query) {
        LambdaQueryWrapper<TenantAuthRoleDO> queryWrapper = new LambdaQueryWrapper<>(TenantAuthRoleDO.class)
                .orderByAsc(TenantAuthRoleDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
                .eq(null != query.getPublishStatus(), TenantAuthRoleDO::getPublishStatus, query.getPublishStatus())
                .eq(StringUtils.isNotBlank(query.getCode()), TenantAuthRoleDO::getCode, query.getCode())
                .like(StringUtils.isNotBlank(query.getName()), TenantAuthRoleDO::getName, query.getName());
        Page<TenantAuthRoleDO> page = tenantAuthRoleMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), queryWrapper);
        if (Collections3.isEmpty(page.getRecords())) {
            return new Page<>();
        }
        Page<TenantAuthRolePageVO> result = BeanUtil.convertPage(page, TenantAuthRolePageVO.class);
        List<TenantAuthRolePageVO> records = result.getRecords();
        List<Long> authRoleIds = records.stream().map(TenantAuthRolePageVO::getId).collect(Collectors.toList());
        //查询关联租户用户数量
        List<TenantAuthRoleUserDO> tenantAuthRoleUserDos = tenantAuthRoleUserMapper.selectList(new LambdaQueryWrapper<>(TenantAuthRoleUserDO.class).in(TenantAuthRoleUserDO::getTenantAuthRoleId, authRoleIds));
        if (Collections3.isEmpty(tenantAuthRoleUserDos)) {
            tenantAuthRoleUserDos = Collections3.emptyList();
        }
        Map<Long, List<TenantAuthRoleUserDO>> userMap = tenantAuthRoleUserDos.stream().collect(Collectors.groupingBy(TenantAuthRoleUserDO::getTenantAuthRoleId));
        //查询关联商户数量
        List<ShopRoleTenantAuthRoleDO> shopRoleTenantAuthRoleDos = shopRoleTenantAuthRoleMapper.selectList(new LambdaQueryWrapper<>(ShopRoleTenantAuthRoleDO.class).in(ShopRoleTenantAuthRoleDO::getTenantAuthId, authRoleIds));
        if (Collections3.isEmpty(shopRoleTenantAuthRoleDos)) {
            shopRoleTenantAuthRoleDos = Collections3.emptyList();
        }
        Map<Long, List<ShopRoleTenantAuthRoleDO>> shopMap = shopRoleTenantAuthRoleDos.stream().collect(Collectors.groupingBy(ShopRoleTenantAuthRoleDO::getTenantAuthId));
        for (TenantAuthRolePageVO s : records) {
            s.setUserCount(userMap.containsKey(s.getId()) ? userMap.get(s.getId()).size() : 0);
            s.setShopCount(shopMap.containsKey(s.getId()) ? shopMap.get(s.getId()).stream().map(ShopRoleTenantAuthRoleDO::getShopId).distinct().collect(Collectors.toList()).size() : 0);
        }
        return result;
    }

    @Override
    public Boolean add(TenantAuthRoleParam param) {
        TenantAuthRoleDO tenantAuthRoleDO = BeanUtil.convertBean(param, TenantAuthRoleDO.class);
        if (checkUnique(tenantAuthRoleDO)) {
            throw new BusinessException("授权角色编码或名称已存在");
        }
        tenantAuthRoleDO.setCreateBy(UserUtils.getUserId());
        tenantAuthRoleDO.setCreateTime(LocalDateTime.now());
        tenantAuthRoleDO.setModifyTime(LocalDateTime.now());
        return tenantAuthRoleMapper.insert(tenantAuthRoleDO) > 0;
    }

    @Override
    public Boolean modify(TenantAuthRoleParam param) {
        TenantAuthRoleDO tenantAuthRoleDO = BeanUtil.convertBean(param, TenantAuthRoleDO.class);
        if (checkUnique(tenantAuthRoleDO)) {
            throw new BusinessException("授权角色编码或名称已存在");
        }
        tenantAuthRoleDO.setModifyBy(UserUtils.getUserId());
        tenantAuthRoleDO.setModifyTime(LocalDateTime.now());
        tenantAuthRoleDO.setCode(null);
        return tenantAuthRoleMapper.updateById(tenantAuthRoleDO) > 0;
    }

    @Override
    public TenantAuthRoleVO view(Long id) {
        TenantAuthRoleBO tenantAuthRoleBO = getBean().queryById(id);
        return BeanUtil.convertBean(tenantAuthRoleBO, TenantAuthRoleVO.class);
    }

    @Override
    public TenantAuthRoleBO queryById(Long id) {
        TenantAuthRoleDO tenantAuthRoleDO = tenantAuthRoleMapper.selectById(id);
        return BeanUtil.convertBean(tenantAuthRoleDO, TenantAuthRoleBO.class);
    }

    @Override
    public Boolean changeStatus(Long id, Integer status) {
        TenantAuthRoleDO tenantAuthRoleDO = new TenantAuthRoleDO();
        tenantAuthRoleDO.setId(id);
        tenantAuthRoleDO.setPublishStatus(status);
        tenantAuthRoleDO.setModifyBy(UserUtils.getUserId());
        tenantAuthRoleDO.setModifyTime(LocalDateTime.now());
        return tenantAuthRoleMapper.updateById(tenantAuthRoleDO) > 0;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Boolean del(Long id) {
        TenantAuthRoleBO tenantAuthRoleBO = getBean().queryById(id);
        if (PublishStatusEnum.ENABLE.getValue().equals(tenantAuthRoleBO.getPublishStatus())) {
            throw new BusinessException("请禁用后再删除");
        }
        //删除角色和用户
        tenantAuthRoleUserMapper.delete(new LambdaQueryWrapper<>(TenantAuthRoleUserDO.class).eq(TenantAuthRoleUserDO::getTenantAuthRoleId, id));
        //删除角色和商户角色关系
        shopRoleTenantAuthRoleMapper.delete(new LambdaQueryWrapper<>(ShopRoleTenantAuthRoleDO.class).eq(ShopRoleTenantAuthRoleDO::getTenantAuthId, id));
        return tenantAuthRoleMapper.deleteById(id) > 0;
    }

    @Override
    public List<TenantAuthRoleUserBO> queryUserIdsByRoleId(Long roleId) {
        List<TenantAuthRoleUserDO> tenantAuthRoleUserDos = tenantAuthRoleUserMapper.selectList(new LambdaQueryWrapper<>(TenantAuthRoleUserDO.class).eq(TenantAuthRoleUserDO::getTenantAuthRoleId, roleId));
        return JsonUtils.jsonToList(tenantAuthRoleUserDos, TenantAuthRoleUserBO.class);
    }

    private Boolean checkUnique(TenantAuthRoleDO roleDO) {
        Integer count = tenantAuthRoleMapper.selectCount(new LambdaQueryWrapper<>(TenantAuthRoleDO.class)
                .ne(null != roleDO.getId(), TenantAuthRoleDO::getId, roleDO.getId())
                .and(
                        Wrapper -> Wrapper
                                .eq(StringUtils.isNotBlank(roleDO.getCode()), TenantAuthRoleDO::getCode, roleDO.getCode())
                                .or()
                                .eq(StringUtils.isNotBlank(roleDO.getName()), TenantAuthRoleDO::getName, roleDO.getName())
                )
        );
        return 0 == count;
    }

    private static ITenantAuthRoleService getBean() {
        return SpringBeanUtil.getBean(ITenantAuthRoleService.class);
    }
}
